package model;

import domain.RawDataDO;
import dto.DayAcquisitionDTO;
import dto.SinglePointDTO;
import model.data.Point;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

/**
 * @author 刀氏春秋
 * @date 2023/6/15
 */
public class DataLoadUtil {
    /**
     * 从列式原始数据中读取并整理电流-电压数据点
     *
     * @param currentData 电流数据
     * @param voltageData 电压数据
     * @return 完整周电流-电压数据
     */
    public List<RawDataDO> getAcquisitionData(List<DayAcquisitionDTO> currentData, List<DayAcquisitionDTO> voltageData) {
        List<RawDataDO> dataList = new LinkedList<>();

        // 记录已读取的电表的资产号
        HashMap<String, RawDataDO> assetNoSet = new HashMap<>();
        Class<DayAcquisitionDTO> dtoClass = DayAcquisitionDTO.class;

        // 取数据循环
        try {
            for (int i = 0; i < currentData.size(); i++) {
                // 对于每一天数据，提取出资产号，判断其是否是第一次加入，如果是的话，将数据导入
                // 排除三相表，总表的实际相位一列是4，
                String assetNo = currentData.get(i).getAssetNo();
                if (currentData.get(i).getWiringMode().equals("3") &&
                        !currentData.get(i).getHplcPhase().equals("0")) {
                    continue;
                }
                // 序号基数
                if (!assetNoSet.containsKey(assetNo)) {
                    // 新电表读入，说明已读取满672个点，该切入到下一段数据的读取
                    RawDataDO data = new RawDataDO();
                    // 设置电表资产号，hplc识别对照结果，接线模式等等
                    data.setAssetNo(assetNo);
                    data.setHplcPhase(currentData.get(i).getHplcPhase());
                    data.setWiringMode(currentData.get(i).getWiringMode());
                    assetNoSet.put(assetNo, data);
                    // 将数据引入
                    dataList.add(assetNoSet.get(assetNo));
                }

                // 导入点数据
                List<Point> points = new LinkedList<>();
                // 对每一个DTO对象，通过反射调用DTO对象的getter，调出数据
                for (int point = 1; point <= 96; point++) {
                    String methodName = "getI" + point;
                    // 准备DO对象的set方法
                    Double current = (Double) dtoClass.getDeclaredMethod(methodName).invoke(currentData.get(i));
                    Double voltage = (Double) dtoClass.getDeclaredMethod(methodName).invoke(voltageData.get(i));
                    // 过滤掉低功率时间
                    points.add(new Point(current, voltage, 0d));
                }
                assetNoSet.get(assetNo).appendList(points);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 总表三相的电表资产号是不同的，为了同步日采集数据处理流程，需将其名置为同一个
        String gatewayNo = dataList.get(0).getAssetNo().split("_")[0];
        dataList.get(0).setAssetNo(gatewayNo);
        dataList.get(1).setAssetNo(gatewayNo);
        dataList.get(2).setAssetNo(gatewayNo);

        return dataList;
    }

    /**
     * 组装总表数据
     *
     * @param phaseA A相电流-电压数据
     * @param phaseB B相电流-电压数据
     * @param phaseC C相电流-电压数据
     * @return 总表数据
     */
    private List<RawDataDO> assembleGatewayRawData(List<Point> phaseA, List<Point> phaseB, List<Point> phaseC, String assetNo) {
        List<RawDataDO> gatewayData = new LinkedList<>();
        // 组装数据
        RawDataDO gatewayA = new RawDataDO();
        RawDataDO gatewayB = new RawDataDO();
        RawDataDO gatewayC = new RawDataDO();

        gatewayA.setPoints(phaseA);
        gatewayA.setWiringMode("3");
        gatewayA.setHplcPhase("0");
        gatewayA.setAssetNo(assetNo);

        gatewayB.setPoints(phaseB);
        gatewayB.setWiringMode("3");
        gatewayB.setHplcPhase("0");
        gatewayB.setAssetNo(assetNo);

        gatewayC.setPoints(phaseC);
        gatewayC.setWiringMode("3");
        gatewayC.setHplcPhase("0");
        gatewayC.setAssetNo(assetNo);

        System.out.printf("size: %d, %d, %d%n", phaseA.size(), phaseB.size(), phaseC.size());
        System.out.println(phaseA);
        System.out.println(phaseB);
        System.out.println(phaseC);

        gatewayData.add(gatewayA);
        gatewayData.add(gatewayB);
        gatewayData.add(gatewayC);
        return gatewayData;
    }

    /**
     * 从行式原始数据中读取并整理电流-电压-功率数据点
     *
     * @param gatewayData 总表数据
     * @param userData    户表数据
     * @return 完整周电流-电压数据
     */
    public List<RawDataDO> getWeekSinglePointData(List<SinglePointDTO> gatewayData, List<SinglePointDTO> userData) {
        List<RawDataDO> dataList = new LinkedList<>();
        // 从Excel表格中读取数据
        ReadExcelUtil<SinglePointDTO> reader = new ReadExcelUtil<>();


        try {
            // 首先读取总表数据
            List<Point> phaseA = new LinkedList<>();
            List<Point> phaseB = new LinkedList<>();
            List<Point> phaseC = new LinkedList<>();

            // 逐个遍历DTO对象，读取总表数据点
            for (SinglePointDTO item : gatewayData) {
                phaseA.add(new Point(item.getPhaseACurrent(), item.getPhaseAVoltage(), item.getPower()));
                phaseB.add(new Point(item.getPhaseBCurrent(), item.getPhaseBVoltage(), item.getPower()));
                phaseC.add(new Point(item.getPhaseCCurrent(), item.getPhaseCVoltage(), item.getPower()));
            }

            dataList.addAll(assembleGatewayRawData(phaseA, phaseB, phaseC, gatewayData.get(0).getAssetNo()));
            System.out.println(dataList);

            // 遍历DTO对象，读取单相表数据点
            for (int i = 0; i < userData.size() / 672; i++) {
                RawDataDO data = new RawDataDO();
                List<Point> points = new LinkedList<>();
                SinglePointDTO item = userData.get(i);

                // 如果B或C相有值，说明为三相表，跳过
                if (item.getPhaseBVoltage() != null || item.getPhaseCVoltage() != null) continue;
                for (int j = 0; j < 672; j++) {
                    points.add(new Point(
                            userData.get(i * 672 + j).getPhaseACurrent(),
                            userData.get(i * 672 + j).getPhaseAVoltage(), item.getPower()));
                }
                data.setAssetNo(userData.get(i * 672).getAssetNo());
                data.setHplcPhase(userData.get(i * 672).getTruePhase());
                data.setWiringMode("1");
                data.setPoints(points);
                dataList.add(data);
            }
        } catch (
                Exception e) {
            e.printStackTrace();
        }

        return dataList;
    }
}
